using System;
using System.Data;
using System.Linq;
using Magiq.Support;

namespace Magiq.Databases
{
    public abstract class CommandBuilder
    {
        protected const string TypeReferenceName = "__TypeReference__";
        private readonly bool addTypeReference;

        protected CommandBuilder(IOrmAdapter ormAdapter, IQueryable where, bool addTypeReference)
        {
            this.addTypeReference = addTypeReference;
            OrmAdapter = ormAdapter;
            Where = where;
        }

        protected PropertyMapping TypeReferenceProperty { get; private set; }
        protected IQueryable Where { get; private set; }
        protected IOrmAdapter OrmAdapter { get; private set; }
        protected IDbCommand Command { get; private set; }
        protected ITypeMapping Mapping { get; private set; }
        protected string BaseTableName { get; set; }

        public string From
        {
            get { return Select.From; }
        }

        protected SelectStatementInformation Select { get; set; }

        protected void SetCommand(IDbCommand command)
        {
            Command = command;
            Command.CommandText = Command.CommandText.ToUpperInvariant();
            BaseTableName = addTypeReference
                                ? Command.CommandText.GetFrom("SELECT").GetUntil(".").Trim()
                                : Mapping.TableName;
            Select = new SelectStatementParser().Parse(Command.CommandText);
        }

        public abstract IDbCommand GetCommand();

        protected virtual void Init(Type elementType)
        {
            Mapping = OrmAdapter.GetMappingOf(elementType);
            TypeReferenceProperty = Mapping.Ids.First();
        }
    }
}